﻿using System.IO;
using System.Windows.Media;
using FluxJpeg.Core;
using FluxJpeg.Core.Decoder;
using FluxJpeg.Core.Encoder;

namespace Gmantis.Imaging
{
    public static class JpgCodec
    {
        // Fields
        internal static byte[] Signature = new byte[] { 0xff, 0xd8, 0xff };

        // Methods
        public static Bitmap Decode(Stream stream)
        {
            Bitmap bmp = new Bitmap();
            Decode(bmp, stream);
            return bmp;
        }

        internal static void Decode(Bitmap bmp, Stream stream)
        {
            try
            {
                bmp.BeginUpdate();
                DecodeInternal(bmp, stream);
            }
            finally
            {
                bmp.EndUpdate();
            }
        }

        private static void DecodeInternal(Bitmap bmp, Stream stream)
        {
            DecodedJpeg jpeg = new JpegDecoder(stream).Decode();
            jpeg.Image.ChangeColorSpace(ColorSpace.RGB);
            bmp.SetSize(jpeg.Image.Width, jpeg.Image.Height);
            byte[][,] raster = jpeg.Image.Raster;
            for (int i = 0; i < bmp.Height; i++)
            {
                for (int j = 0; j < bmp.Width; j++)
                {
                    byte red = raster[0][j, i];
                    byte green = raster[1][j, i];
                    byte blue = raster[2][j, i];
                    bmp.SetPixel(j, i, red, green, blue, 0xff);
                }
            }
        }

        public static Stream Encode(Bitmap bmp)
        {
            return Encode(bmp, 80);
        }

        public static Stream Encode(Bitmap bmp, int quality)
        {
            ColorModel cm = new ColorModel
            {
                Opaque = true,
                colorspace = ColorSpace.RGB
            };
            byte[][,] raster = FluxJpeg.Core.Image.CreateRaster(bmp.Width, bmp.Height, 3);
            for (int i = 0; i < bmp.Height; i++)
            {
                for (int j = 0; j < bmp.Width; j++)
                {
                    Color pixel = bmp.GetPixel(j, i);
                    raster[0][j, i] = pixel.R;
                    raster[1][j, i] = pixel.G;
                    raster[2][j, i] = pixel.B;
                }
            }
            FluxJpeg.Core.Image image = new FluxJpeg.Core.Image(cm, raster);
            MemoryStream outStream = new MemoryStream();
            new JpegEncoder(image, quality, outStream).Encode();
            outStream.Seek(0L, SeekOrigin.Begin);
            return outStream;
        }
    }
}
